/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.openide.src; import java.io.Serializable; import java.util.*; /** Support class that manages set of objects and fires events * about its changes. * * @author Jaroslav Tulach */ class MemoryCollection extends Object implements Serializable { /** array of objects */ LinkedList array; /** Object to fire info about changes to */ ClassElement.Memory memory; /** name of property to fire */ private String propertyName; /** array template to return */ private Object[] template; static final long serialVersionUID =-9215370960397120952L; /** * @param memory memory element to fire changes to * @param propertyName name of property to fire when array changes * @param emptyArray emptyArray instance that provides the type of arrays * that should be returned by toArray method */ public MemoryCollection( ClassElement.Memory memory, String propertyName, Object[] emptyArray ) { this.memory = memory; this.propertyName = propertyName; this.template = emptyArray; } /** Changes the content of this object. * @param arr array of objects to change * @param action the action to do */ public void change (Object[] arr, int action) { change (Arrays.asList (arr), action); } /** Changes the content of this object. * @param c collection of objects to change * @param action the action to do */ protected void change (Collection c, int action) { boolean anChange; switch (action) { case ClassElement.Impl.ADD: anChange = c.size () > 0; if (array != null) { array.addAll (c); break; } // fall thru to initialize the array case ClassElement.Impl.SET: // PENDING: better change detection; currently any SET operation will fire change. anChange = c.size () > 0 || (array != null && array.size () > 0); array = new LinkedList (c); break; case ClassElement.Impl.REMOVE: anChange = array != null && array.removeAll (c); default: // illegal argument in internal implementation throw new InternalError (); } if (anChange) { // do not construct array values if not necessary memory.firePropertyChange (propertyName, null, null); } } /** Access to the array. * @return array of objects contained here */ public Object[] toArray () { if (array == null) { return template; } else { return array.toArray (template); } } /** Special collection for initializers. Provides declaringClass field. */ static final class Initializer extends MemoryCollection { private static final InitializerElement[] EMPTY = new InitializerElement[0]; static final long serialVersionUID =5715072242254795093L; /** * @param memory memory element to fire changes to * @param propertyName name of property to fire when array changes * @param emptyArray emptyArray instance that provides the type of arrays * that should be returned by toArray method */ public Initializer ( ClassElement.Memory memory ) { super (memory, ElementProperties.PROP_INITIALIZERS, EMPTY); } /** Changes the content of this object. * @param c collection of objects to change * @param action the action to do */ protected void change (Collection c, int action) { boolean anChange; switch (action) { case ClassElement.Impl.ADD: case ClassElement.Impl.SET: // clone the nodes Iterator it = c.iterator (); c = new ArrayList (); while (it.hasNext ()) { InitializerElement el = (InitializerElement)it.next (); // clone the element el = new InitializerElement (new InitializerElement.Memory ( el ), memory.getClassElement ()); c.add (el); } } super.change (c, action); } } /** Collection for members. Assignes to each class its * members. */ static abstract class Member extends MemoryCollection { static final long serialVersionUID =7875426480834524238L; /** * @param memory memory element to fire changes to * @param propertyName name of property to fire when array changes * @param emptyArray emptyArray instance that provides the type of arrays * that should be returned by toArray method */ public Member ( ClassElement.Memory memory, String propertyName, Object[] emptyArray ) { super (memory, propertyName, emptyArray); } /** Changes the content of this object. * @param c collection of objects to change * @param action the action to do */ protected void change (Collection c, int action) { boolean anChange; switch (action) { case ClassElement.Impl.ADD: case ClassElement.Impl.SET: // clone the nodes Iterator it = c.iterator (); c = new ArrayList (); while (it.hasNext ()) { c.add (clone (it.next ())); } } super.change (c, action); } /** Find method that looks in member elements * @param id the indetifier (or null) * @param types array of types to test (or null) * @return the element or null */ public MemberElement find (Identifier id, Type[] types) { if (array == null) return null; Iterator it = array.iterator (); while (it.hasNext ()) { MemberElement me = (MemberElement)it.next (); if ( (id == null || id.equals(me.getName ())) && // types can be non-null only for Method or Constructor Elements (types == null || equalTypes (types, me)) ) { // found element return me; } } // nothing found return null; } /** Copares given types to types of the element. * The element must be ConstructorElement * * @param types the types * @param el the element * @return true if types are equal */ private static boolean equalTypes (Type[] types, MemberElement el) { // can be called only for ConstructorElement MethodParameter[] test = ((ConstructorElement)el).getParameters (); // number if (test.length != types.length) return false; int l = test.length; for (int i = 0; i < l; i++) { if (!test[i].getType().equals(types[i])) return false; } return true; } /** Clones the object. * @param obj object to clone * @return cloned object */ protected abstract MemberElement clone (Object obj); } /** Collection for members. Assignes to each class its * members. */ static class Constructor extends Member { private static final ConstructorElement[] EMPTY = new ConstructorElement[0]; static final long serialVersionUID =4314343816469864217L; /** @param ce class element memory impl to work in */ public Constructor (ClassElement.Memory ce) { super (ce, ElementProperties.PROP_CONSTRUCTORS, EMPTY); } /** Clones the object. * @param obj object to clone * @return cloned object */ protected MemberElement clone (Object obj) { ConstructorElement.Memory m = new ConstructorElement.Memory ((ConstructorElement)obj); Identifier id = memory.getName(); if (id != null) { m.setName(Identifier.create(id.getName())); } return new ConstructorElement(m, memory.getClassElement()); } } /** Collection for methods. */ static class Method extends Member { private static final MethodElement[] EMPTY = new MethodElement[0]; static final long serialVersionUID =-745714645316747109L; /** @param ce class element memory impl to work in */ public Method (ClassElement.Memory ce) { super (ce, ElementProperties.PROP_METHODS, EMPTY); } /** Clones the object. * @param obj object to clone * @return cloned object */ protected MemberElement clone (Object obj) { return new MethodElement (new MethodElement.Memory ( (MethodElement)obj ), memory.getClassElement ()); } } /** Collection of fields. */ static class Field extends Member { private static final FieldElement[] EMPTY = new FieldElement[0]; static final long serialVersionUID =5747776340409139399L; /** @param ce class element memory impl to work in */ public Field (ClassElement.Memory ce) { super (ce, ElementProperties.PROP_FIELDS, EMPTY); } /** Clones the object. * @param obj object to clone * @return cloned object */ protected MemberElement clone (Object obj) { return new FieldElement (new FieldElement.Memory ( (FieldElement)obj ), memory.getClassElement ()); } } /** Collection of class. */ static class Class extends Member { private static final ClassElement[] EMPTY = new ClassElement[0]; static final long serialVersionUID =3206093459760846163L; /** @param ce class element memory impl to work in */ public Class (ClassElement.Memory ce) { super (ce, ElementProperties.PROP_CLASSES, EMPTY); } /** Clones the object. * @param obj object to clone * @return cloned object */ protected MemberElement clone (Object obj) { ClassElement.Memory ceMem = new ClassElement.Memory ( (ClassElement)obj ); ceMem.copyFrom((ClassElement) obj); return new ClassElement(ceMem, memory.getClassElement()); } } } /* * Log * 19 Gandalf-post-FCS1.16.1.1 4/19/00 Svatopluk Dedic * 18 Gandalf-post-FCS1.16.1.0 4/18/00 Svatopluk Dedic PropertyChange event * firing improved * 17 src-jtulach1.16 12/21/99 Ales Novak the clone method of Class * clones also interfaces, methods, etc. * 16 src-jtulach1.15 12/8/99 Petr Hamernik compilable by Javac V8 * (jdk1.3) * 15 src-jtulach1.14 10/22/99 Ian Formanek NO SEMANTIC CHANGE - Sun * Microsystems Copyright in File Comment * 14 src-jtulach1.13 10/7/99 Petr Hamernik finding elements bug fix. * 13 src-jtulach1.12 9/29/99 Petr Hamernik just indentation * 12 src-jtulach1.11 8/9/99 Ian Formanek Generated Serial Version * UID * 11 src-jtulach1.10 8/9/99 Ian Formanek Generated Serial Version * UID * 10 src-jtulach1.9 8/4/99 Petr Hamernik fixed bug #3135 * 9 src-jtulach1.8 6/8/99 Ian Formanek ---- Package Change To * org.openide ---- * 8 src-jtulach1.7 6/7/99 Petr Hamernik adding bug fixed * 7 src-jtulach1.6 5/12/99 Petr Hamernik Identifier implementation * updated * 6 src-jtulach1.5 2/26/99 Petr Hamernik bugfixes * 5 src-jtulach1.4 2/17/99 Petr Hamernik serialization changed. * 4 src-jtulach1.3 1/19/99 Jaroslav Tulach * 3 src-jtulach1.2 1/19/99 Jaroslav Tulach * 2 src-jtulach1.1 1/19/99 Jaroslav Tulach * 1 src-jtulach1.0 1/19/99 Jaroslav Tulach * $ */